package com.ryder.petmatediarybackend.module.shop.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ryder.petmatediarybackend.common.exception.BusinessException;
import com.ryder.petmatediarybackend.module.shop.dto.CreateShopDTO;
import com.ryder.petmatediarybackend.module.shop.dto.UpdateShopDTO;
import com.ryder.petmatediarybackend.module.shop.entity.ShopInfo;
import com.ryder.petmatediarybackend.module.shop.mapper.ShopInfoMapper;
import com.ryder.petmatediarybackend.module.shop.service.ShopInfoService;
import com.ryder.petmatediarybackend.module.shop.vo.ShopInfoVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 描述: 店铺基础信息表（每个用户仅拥有一个店铺）(ShopInfo)表服务实现类
 * 
 * @author Ryder
 * @version 1.0
 * @since 1.0
 * 更新日期: 2025-10-31
 */
@Slf4j
@Service("shopInfoService")
@RequiredArgsConstructor
public class ShopInfoServiceImpl extends ServiceImpl<ShopInfoMapper, ShopInfo> implements ShopInfoService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ShopInfoVO createShop(Long userId, CreateShopDTO dto) {
        log.info("[创建店铺] userId={}, shopName={}", userId, dto.getShopName());

        // 检查是否已有店铺
        if (hasShop(userId)) {
            throw new BusinessException("您已经拥有一个店铺，无法重复创建");
        }

        // 创建店铺
        ShopInfo shopInfo = new ShopInfo();
        BeanUtil.copyProperties(dto, shopInfo);
        shopInfo.setUserId(userId);
        
        // 设置图片JSON字段
        if (dto.getFacadeImages() != null && !dto.getFacadeImages().isEmpty()) {
            shopInfo.setFacadeImages(JSONUtil.toJsonStr(dto.getFacadeImages()));
        }
        if (dto.getInteriorImages() != null && !dto.getInteriorImages().isEmpty()) {
            shopInfo.setInteriorImages(JSONUtil.toJsonStr(dto.getInteriorImages()));
        }

        // 设置默认状态
        shopInfo.setHasVaccinePermission(0); // 默认无疫苗权限
        shopInfo.setStatus(3); // 审核中
        shopInfo.setAuditStatus(0); // 待审核

        boolean saved = this.save(shopInfo);
        if (!saved) {
            throw new BusinessException("创建店铺失败");
        }

        log.info("[创建店铺成功] shopId={}", shopInfo.getId());
        return convertToVO(shopInfo);
    }

    @Override
    public ShopInfoVO getMyShop(Long userId) {
        ShopInfo shopInfo = getShopByUserId(userId);
        if (shopInfo == null) {
            return null;
        }
        return convertToVO(shopInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ShopInfoVO updateShop(Long userId, UpdateShopDTO dto) {
        log.info("[更新店铺] userId={}", userId);

        ShopInfo shopInfo = getShopByUserId(userId);
        if (shopInfo == null) {
            throw new BusinessException("店铺不存在");
        }

        // 更新店铺信息
        BeanUtil.copyProperties(dto, shopInfo, "id", "userId");
        
        // 更新图片JSON字段
        if (dto.getFacadeImages() != null) {
            shopInfo.setFacadeImages(JSONUtil.toJsonStr(dto.getFacadeImages()));
        }
        if (dto.getInteriorImages() != null) {
            shopInfo.setInteriorImages(JSONUtil.toJsonStr(dto.getInteriorImages()));
        }

        boolean updated = this.updateById(shopInfo);
        if (!updated) {
            throw new BusinessException("更新店铺失败");
        }

        log.info("[更新店铺成功] shopId={}", shopInfo.getId());
        return convertToVO(shopInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteShop(Long userId) {
        log.info("[删除店铺] userId={}", userId);

        ShopInfo shopInfo = getShopByUserId(userId);
        if (shopInfo == null) {
            throw new BusinessException("店铺不存在");
        }

        boolean deleted = this.removeById(shopInfo.getId());
        if (!deleted) {
            throw new BusinessException("删除店铺失败");
        }

        log.info("[删除店铺成功] shopId={}", shopInfo.getId());
    }

    @Override
    public boolean hasShop(Long userId) {
        LambdaQueryWrapper<ShopInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ShopInfo::getUserId, userId);
        return this.count(wrapper) > 0;
    }

    @Override
    public ShopInfo getShopByUserId(Long userId) {
        LambdaQueryWrapper<ShopInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ShopInfo::getUserId, userId);
        return this.getOne(wrapper);
    }

    /**
     * 转换为VO
     */
    private ShopInfoVO convertToVO(ShopInfo shopInfo) {
        ShopInfoVO vo = new ShopInfoVO();
        BeanUtil.copyProperties(shopInfo, vo);

        // 解析JSON字段
        if (shopInfo.getFacadeImages() != null) {
            vo.setFacadeImages(JSONUtil.toList(shopInfo.getFacadeImages(), String.class));
        }
        if (shopInfo.getInteriorImages() != null) {
            vo.setInteriorImages(JSONUtil.toList(shopInfo.getInteriorImages(), String.class));
        }

        // 设置文本字段
        vo.setShopTypeText(getShopTypeText(shopInfo.getShopType()));
        vo.setStatusText(getStatusText(shopInfo.getStatus()));
        vo.setAuditStatusText(getAuditStatusText(shopInfo.getAuditStatus()));

        return vo;
    }

    /**
     * 获取店铺类型文本
     */
    private String getShopTypeText(Integer shopType) {
        if (shopType == null) {
            return "未知";
        }
        return switch (shopType) {
            case 1 -> "宠物店";
            case 2 -> "宠物医院";
            case 3 -> "宠物美容";
            case 4 -> "综合";
            default -> "未知";
        };
    }

    /**
     * 获取状态文本
     */
    private String getStatusText(Integer status) {
        if (status == null) {
            return "未知";
        }
        return switch (status) {
            case 1 -> "营业中";
            case 2 -> "已打烊";
            case 3 -> "审核中";
            case 4 -> "已冻结";
            default -> "未知";
        };
    }

    /**
     * 获取审核状态文本
     */
    private String getAuditStatusText(Integer auditStatus) {
        if (auditStatus == null) {
            return "未知";
        }
        return switch (auditStatus) {
            case 0 -> "待审核";
            case 1 -> "审核通过";
            case 2 -> "审核驳回";
            default -> "未知";
        };
    }

    @Override
    public List<ShopInfoVO> getNearbyShops(Double longitude, Double latitude, Double radius) {
        log.info("[获取附近店铺] longitude={}, latitude={}, radius={}", longitude, latitude, radius);
        
        // 获取所有营业中的店铺
        LambdaQueryWrapper<ShopInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ShopInfo::getStatus, 1)
                .eq(ShopInfo::getAuditStatus, 1);
        
        List<ShopInfo> allShops = this.list(wrapper);
        
        // 计算距离并过滤
        List<ShopInfo> nearbyShops = allShops.stream()
                .filter(shop -> calculateDistance(latitude, longitude, shop.getLatitude(), shop.getLongitude()) <= radius)
                .toList();
        
        log.info("[获取附近店铺成功] 数量={}", nearbyShops.size());
        return nearbyShops.stream().map(this::convertToVO).toList();
    }

    @Override
    public List<ShopInfoVO> getAllActiveShops() {
        log.info("[获取所有营业中店铺]");
        
        LambdaQueryWrapper<ShopInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ShopInfo::getStatus, 1)
                .eq(ShopInfo::getAuditStatus, 1)
                .orderByDesc(ShopInfo::getCreateTime);
        
        List<ShopInfo> shops = this.list(wrapper);
        log.info("[获取所有营业中店铺成功] 数量={}", shops.size());
        return shops.stream().map(this::convertToVO).toList();
    }

    @Override
    public ShopInfoVO getShopDetail(Long shopId) {
        log.info("[获取店铺详情] shopId={}", shopId);
        
        ShopInfo shopInfo = this.getById(shopId);
        if (shopInfo == null) {
            throw new BusinessException("店铺不存在");
        }
        
        return convertToVO(shopInfo);
    }

    /**
     * 计算两点之间的距离（单位：公里）
     * 使用Haversine公式
     */
    private double calculateDistance(Double lat1, Double lon1, Double lat2, Double lon2) {
        final double EARTH_RADIUS = 6371; // 地球半径（公里）
        
        double dLat = Math.toRadians(lat2 - lat1);
        double dLon = Math.toRadians(lon2 - lon1);
        
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                   Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
                   Math.sin(dLon / 2) * Math.sin(dLon / 2);
        
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        
        return EARTH_RADIUS * c;
    }
}
